﻿using System;
using System.Linq;
using System.Collections.Generic;
using Domain.Core;
using Domain.MainModule.Entities;
using Domain.MainModule.Addresses;
using Domain.MainModule.AddressTypes;

namespace Application.MainModule.AddressManagement
{
    public class AddressManagementService : IAddressManagementService, IDisposable
    {
        #region private properties

        private IAddressRepository AddressRepository
        {
            get;
            set;
        }

        private IAddressTypeRepository AddressTypeRepository
        {
            get;
            set;
        }

        #endregion

        #region constructor

        /// <summary>
        /// Default constructor for AddressService.
        /// </summary>
        /// <param name="addressRepository">AddressRepository dependency, usually this is resolved by IoC</param>
        public AddressManagementService(IAddressRepository addressRepository)
        {
            if (addressRepository == (IAddressRepository)null)
            {
                throw new ArgumentNullException(Resources.Messages.exception_DependenciesAreNotInitialized);
            }

            this.AddressRepository = addressRepository;
        }

        #endregion

        #region IAddressService implementations

        public void AddAddress(Address address)
        {
            IUnitOfWork unitOfWork = this.AddressRepository.UnitOfWork as IUnitOfWork;
            this.AddressRepository.Add(address);
            unitOfWork.Commit();
        }

        public void ChangeAddress(Address address)
        {
            IUnitOfWork unitOfWork = this.AddressRepository.UnitOfWork as IUnitOfWork;
            this.AddressRepository.Modify(address);
            unitOfWork.CommitAndRefreshChanges();
        }

        public Address FindAddressById(Guid addressId)
        {
            AddressIdSpecification addressIdSpecification = new AddressIdSpecification(addressId);
            return this.AddressRepository.FindAddress(addressIdSpecification);
        }

        public List<Address> FindAddressByUserId(Guid userId)
        {
            AddressUserIdSpecification addressUserIdSpecification = new AddressUserIdSpecification(userId);
            return this.AddressRepository.FindAddresses(addressUserIdSpecification).ToList<Address>();
        }

        public void RemoveAddress(Address address)
        {
            if (address == (Address)null)
                throw new ArgumentNullException("address");

            IUnitOfWork unitOfWork = this.AddressRepository.UnitOfWork as IUnitOfWork;
            this.AddressRepository.Remove(address);
            unitOfWork.CommitAndRefreshChanges();

        }

        public List<AddressType> FindAddressTypeByName(string addressTypeName)
        {
            AddressTypeNameSpecification specification = new AddressTypeNameSpecification(addressTypeName);
            return this.AddressTypeRepository.GetBySpec(specification).ToList();
        }

        #endregion

        #region IDisposable implementations

        /// <summary>
        /// Dispose associated context with this domain service.
        /// </summary>
        public void Dispose()
        {
            if (this.AddressRepository != null
                &&
                this.AddressRepository.UnitOfWork != null)
            {
                this.AddressRepository.UnitOfWork.Dispose();
            }
        }

        #endregion
    }
}
